// interfac接口实现之函数描述
// 接口能够描述jsvascript中对象拥有的各种各样的特性
// 除了描述带有属性的普通对象外, 接口也可以描述函数类型

// 类型检测
interface fncheck{
//  (参数名:参数类型,参数名:参数类型):返回值类型
    (s:string,n:number):string;
}
let fn:fncheck = function(a,b){
    return a+b
}
fn('1',2);

interface SearchFunc{
    // (参数名:参数类型,参数名:参数类型):返回值类型
    (source:string,subString:string):boolean;
}
let mySearch:SearchFunc;
mySearch = function(f:string,s:string){
    let result = f.search(s);
    return result > -1
}
mySearch('11','22');
// 需要string
// 对于函数类型的类型检查来说, 
// 函数的参数名不需要与接口里定义的名字相匹配


// interface接口实现之只读属性
// 接口不仅可以用在函数的传参上, 也可以用于其他语句
// 比如,一些对象属性只能在对象刚刚创建的是否修改其值
// 你可以在属性名前用readonly来指定只读属性:


// 创造接口
interface Point{
    readonly x:number;
    readonly y:number;
}
let p1:Point = {x:10,y:20};

// 创建新对象, 并运用接口进行匹配, 得到并固定值
// 错误! 一旦固定了值之后就不在允许修改
// p1.x = 5;
// 对简单判断该用readonly还是const的方法
// 是要把它看做为变量使用还是作为一个属性.
// 作为变量使用的话用const,
// 若做为属性则使用readonly


// interface接口实现之索引类型
// 与使用几口描述类型差不多, 
// 我们也可以描述那些能够 "通过索引得到" 的类型, 
// 比如a[0]或ageMap["daniel"] 

// 我们定义了StringArray接口, 它具有索引签名
// 这个索引签名表示了当用number去索引StringArray时
// 会得到string类型的返回值

// interface StringArray{
//     // 定义一个索引为数字, 值为字符串的名值对(不一定是数组)
//     [index:number]:string;
// }
// let myArray: StringArray,myObject:StringArray;
// myArray = ["万章","银时"];
// myObject = {0:"万章",1:"银时"};
// let myStr1:string =  myArray[0]   
// let myStr2:string = myObject[0]   

// interface proCheck{
//     [index:string]:string;
//     [index:number]:string;
// }
// interface fncheck{
//     (s:string,n:number):string
// }
// let fn2:fncheck= function(a,b){
//     return a+b
// }
// let obj:proCheck={
//     "name":"万章",
//     9527:"182"  
// }
// console.log(obj[9527]);
// obj[9527] = "1314520"



interface proCheck{
    [indexe:string]:string;
    readonly [indexe:number]:string;
}
interface fncheck{
    (s:string,n:string):string;
}
interface classCheck {
    // constructor(s:string,n:number):string;
    // clockDate:Date;
    getDate():Date;
}
class colock implements classCheck{
    constructor(n,s){
    }
    // clockDate:new Date();
    getDate(){
        return new Date();
    }

}

// interface 接口实现之 "类class" 类型
// 实现类接口的关键字是 implements( 英文释义为: 使生效,执行)
// 利用类接口的设计可以规范出一个标准类最起码所具备的属性和方法

interface ClockInterface{
    currentTime:Date;
    setTime(d:Date);
}
class Clock implements ClockInterface{
    currentTime:Date;
    setTime(d:Date){
        this.currentTime = d;
    }
    constructor(h:number,m:number){}
}


// interface接口实现之继承接口
// 和类一样,接口也可以相互继承
// 这让我们能够从一个接口里复制成员到另一个接口里
// 可以更灵活地将接口分割到可重用的模块里

// interface Shape{
//     color:number;
// }
// interface Square extends Shape{
//     sideLength:number;
// }
// let square:Square={
//     color:65,//color必须是string
//     sideLength:18
// }

// 一个接口也可以继承多个接口,
// 创建出多个接口的合成接口,
// 三苗栗的代码允许结果是,
// 一个调用了Square接口的对象里面必须有color,penWidth,sideLength属性
interface Shape{
    color:string;
}
interface PenStroke{
    penWidth:number;
}
interface Square extends Shape,PenStroke{
    sideLength:number;
}
let square:Square={
    color:"65",
    penWidth:1,
    sideLength:18
}
    

// 接口实现之 混合类型
// 函数也是对象!!! 
// 所以我们可以给一个函数制定一个接口,
// 定义函数的传参和自定义的额外属性
interface Counter{
    // 有一个函数,函数传参是start,
    // 值是number类型,函数返回值是string
    (start:number):string;
    // 一个值是数字的属性
    interval:number;
    // 没啥返回值的函数
    reset():void;
}
function getCounter():Counter{
    let counter = <Counter>function(start:number){
        console.log(start+"");
        return start + "";
    }
    counter.interval = 123;
    counter.reset = function(){};
    return counter;
}
let c = getCounter();
// 调用
c(10);
c.interval = 1;
c.reset();


// interface 接口实现之 接口继承类

// selectableConyrol 包含了Control的所有成员,
// 包括私有成员state

// 因为只有Control的子类才能够拥有一个声明于Contrl的私有成员state
// 这对私有成员的兼容性是必须的,
// 所以只能够是Control的子类们才能实现SelectableControl接口

class Control{
    // 私有成员
    private state:any;
}
interface selectableConyrol extends Control{
    // 创造了一个新的接口, 
    // 这个接口的要求是得有一个私有属性state和一个select方法
    select():void;
}
class Button extends Control implements selectableConyrol{
    // 正确, 因为直接拓展自Control所以就把Control的私有属性一块继承来了
    select(){};
}
// 错误: " Image " 类型缺啥 " state " 属性
class Images extends Control implements selectableConyrol{
    // Image 里面没有state私有属性
    select(){};
}
